﻿/**
 * 封装了一系列帮助方法，用来处理和服务器的通信。
 */
Ext.define('Happy.Ajax', {
    singleton: true,

    /**
     * @readonly
     * @property 通信进度条的提示标题。
     */
    WAIT_TITLE: '温馨提示',
    /**
     * @readonly
     * @property 通信进度条的提示消息。
     */
    WAIT_MSG: '正在努力和服务器通信中，请不要着急！',
    /**
     * @readonly
     * @property 服务器内部出现错误时的提示消息。
     */
    AJAX_FAILURE_MSG: '服务器内部错误',

    /**
     * 加载记录。
     *
     * 如果 option.showWaiter 为 true，在和服务器通信期间会弹出一个进度条，默认为 true。
     * 如果 option.url 没有值，modelClass.getProxy().api.load 有值，会使用
     * modelClass.getProxy().api.load 的值对应的地址执行加载请求。
     * 
     * @param {Ext.Class} modelClass 模型类型
     * @param {Object} id 主键
     * @param {Object} option Ext.data.Model#load() 可以接受的配置对象
     */
    load: function (modelClass, id, option) {
        var me = this;

        option = option || {};

        if (modelClass.getProxy().api.load) {
            Ext.applyIf(option, {
                url: modelClass.getProxy().api.load
            });
        }

        me.interceptorSuccessAndFailureWithWaiter(option);

        modelClass.load(id, option);
    },

    /**
     * 保存记录。
     *
     * 如果 option.showWaiter 为 true，在和服务器通信期间会弹出一个进度条，默认为 true。
     * 
     * @param {Ext.data.Model} record 记录
     * @param {Object} option Ext.data.Model.save() 可以接受的配置对象
     */
    save: function (record, option) {
        var me = this;

        option = option || {};

        me.interceptorSuccessAndFailureWithWaiter(option);

        record.save(option);
    },

    /**
     * 删除记录。
     * 
     * 如果 option.showWaiter 为 true，在和服务器通信期间会弹出一个进度条，默认为 true。
     *
     * @param {Ext.data.Model} record 记录
     * @param {Object} option Ext.data.Model.destroy() 可以接受的配置对象
     */
    destroy: function (record, option) {
        var me = this;

        me.interceptorSuccessAndFailureWithWaiter(option);

        record.destroy(option);
    },

    /**
     * 删除树形结构的模型的记录。
     * 
     * 如果 option.showWaiter 为 true，在和服务器通信期间会弹出一个进度条，默认为 true。 
     * 树形结构只能这样删除，否则会出错，官方文档给出的示例也是这样。
     *
     * @param {Ext.data.TreeStore} store 树形仓储
     * @param {Ext.data.NodeInterface} record 记录
     * @param {Object} option Ext.data.Model.destroy() 可以接受的配置对象
     */
    destroyTreeRecord: function (store, record, option) {
        var me = this;

        option = option || {};
        
        record.remove();
        
        me.interceptorSuccessAndFailureWithWaiter(option);
        
        store.sync(option);
    },

    /**
     * 执行 asp.mvc 中控制器的action。
     *
     * 如果 option.showWaiter 为 true，在和服务器通信期间会弹出一个进度条，默认为 true。
     * 如果 option.encodeParams 为 true，会自动采用 JSON 格式编码所有参数，默认为 true。
     * 服务器返回的数据格式必须包含 { success: true|false }，这样做的目的是为了区分业务层面是否成功，否则
     * 你只知道通信层面是否成功。
     * 
     * @param {Object} option Ext.Ajax.request() 可以接受的配置对象
     */
    callAction: function (option) {
        var me = this;

        var success = option.success || Ext.emptyFn;
        delete option.success;

        var failure = option.failure || Ext.emptyFn;
        delete option.failure;

        if (option.encodeParams !== false) {
            if (option.params) {
                Ext.Object.each(option.params, function (key, value) {
                    option.params[key] = Ext.encode(value);
                });
            }
        }

        Ext.apply(option, {
            success: function (response) {
                var result = Ext.decode(response.responseText);

                if (result.success) {
                    success.apply(option.scope || window, [result]);
                }
                else {
                    failure.apply(option.scope || window, [result]);
                }
            },
            failure: function () {
                failure.apply(option.scope || window, [{ success: false, message: me.AJAX_FAILURE_MSG }]);
            }
        });

        me.interceptorSuccessAndFailureWithWaiter(option);

        Ext.Ajax.request(option);
    },

    /**
     * 如果 option.showWaiter 为 true，拦截 option.success 和 option.failure，在执行期间弹出一个进度条，默认为 true。
     *
     * @private
     * @param {Object} option
     */
    interceptorSuccessAndFailureWithWaiter: function (option) {
        var me = this;

        if (option.showWaiter === false) {
            return;
        }

        var waiter = Ext.Msg.wait(me.WAIT_MSG, me.WAIT_TITLE);

        option.success = Ext.Function.createInterceptor(option.success || Ext.emptyFn, function () {
            waiter.close();
        }, option.scope || window);

        option.failure = Ext.Function.createInterceptor(option.failure || Ext.emptyFn, function () {
            waiter.close();
        }, option.scope || window);
    }
});